<!doctype html>
<html class="no-js" lang="">
<head>
  <meta charset="utf-8">
  <title></title>
  <style>
    table {
      caption-side: top;
      width: auto;
      border-collapse: collapse;
      empty-cells: hide;
    }
    td {
      width: 30px;
      height: 30px;
    }
    .control_button {
      width: 200px;
      height: 200px;
    }
  </style>
</head>
<body>
  <div id="app" tabindex="0" @keydown="controlDirection">
    <table border="1">
      <tr v-for="(rowItem, rowIndex) in table">
        <template v-for="(item, colIndex) in table[rowIndex]">
          <td :style="item.status === 1 || item.status === 2 ? ('background-color: ' + item.color) : ''"></td>
        </template>
      </tr>
    </table>
    <button class="control_button" @click="controlDirection({'key': 'w'})">上</button>
    <button class="control_button" @click="controlDirection({'key': 'd'})">右</button>
    <button class="control_button" @click="controlDirection({'key': 's'})">下</button>
    <button class="control_button" @click="controlDirection({'key': 'a'})">左</button>
  </div>
</body>
<script src="js/vue.js"></script>
<script>
  new Vue({
    el: "#app",
    data: {
      width: 30,
      height: 20,
      defaultSelectColor: '#F36303',
      initLength: 3,
      direction: 1,
      interval: null,
      intervalTime: 500,
      food: {
        x: -1,
        y: -1
      },
      table: [],
      snake: [],
    },
    methods: {
      /**
       * 初始化表格
       */
      initTable() {
        this.table = [];
        for (let i = 0; i < this.height; i++) {
          this.table.push([]);
          for (let j = 0; j < this.width; j++) {
            this.table[i].push({
              status: 0,
              color: ''
            });
          }
        }
      },
      /**
       * 初始化蛇
       */
      initSnake() {
        this.snake = [];
        for (let i = this.initLength - 1; i >= 0; i--) {
          this.snake.push({
            x: i,
            y: 0,
            color: this.defaultSelectColor,
            direction: 1
          });
        }
      },
      /**
       * 是否是活着的蛇
       * @param x
       * @param y
       * @returns {boolean}
       */
      isSnakeAlive(x, y) {
        if (x >= 0 && y >= 0 && x < this.width && y < this.height) {
          for (let i = 1; i < this.snake.length; i++) {
            if (this.snake[i].x === x && this.snake[i].y === y) {
              return false;
            }
          }
          return true;
        } else {
          return false;
        }
      },
      /**
       * 显示蛇
       */
      showSnake() {
        if (this.isSnakeAlive(this.snake[0].x, this.snake[0].y)) {
          this.snake.forEach(o => {
            this.$set(this.table[o.y][o.x], 'status', 1);
            this.$set(this.table[o.y][o.x], 'color', o.color);
          });
        } else {
          alert(`你的得分是${this.snake.length - 3}分！`);
          this.initGame();
        }
      },
      /**
       * 初始化食物
       */
      initFood() {
        let x = Math.floor(Math.random() * this.width);
        let y = Math.floor(Math.random() * this.height);
        let flag = true;
        for (let o of this.snake) {
          if (o.x === x && o.y === y) {
            flag = false;
            this.initFood();
            break;
          }
        }
        if (flag) {
          this.food.x = x;
          this.food.y = y;
          this.$set(this.table[y][x], 'status', 2);
          this.$set(this.table[y][x], 'color', '#0020ff');
        }
      },
      /**
       * 初始化游戏
       */
      initGame() {
        this.direction = 1;
        // 初始化时间间隔
        this.intervalTime = 500;
        // 初始化表格
        this.initTable();
        // 初始化蛇
        this.initSnake();
        // 显示蛇
        this.showSnake();
        // 初始化食物
        this.initFood();
        // 时间间隔
        this.initSpeed();
      },
      /**
       * 下一步的蛇
       */
      nextSnake() {
        let lastX = -1;
        let lastY = -1;
        let tempX = -1;
        let tempY = -1;
        for (let i = 0; i < this.snake.length; i++) {
          if (i === 0) {
            lastX = this.snake[i].x;
            lastY = this.snake[i].y;
            if (this.direction === 0) {
              this.$set(this.snake[i], 'y', this.snake[i].y - 1);
            } else if (this.direction === 1) {
              this.$set(this.snake[i], 'x', this.snake[i].x + 1);
            } else if (this.direction === 2) {
              this.$set(this.snake[i], 'y', this.snake[i].y + 1);
            } else if (this.direction === 3) {
              this.$set(this.snake[i], 'x', this.snake[i].x - 1);
            }
          } else {
            if (i === this.snake.length - 1) {
              this.$set(this.table[this.snake[i].y][this.snake[i].x], 'status', 0);
            }
            tempX = this.snake[i].x;
            tempY = this.snake[i].y;
            this.$set(this.snake[i], 'x', lastX);
            this.$set(this.snake[i], 'y', lastY);
            lastX = tempX;
            lastY = tempY;
          }
        }
        this.eatFood();
        this.showSnake();
      },
      /**
       * 吃食物
       */
      eatFood() {
        if (this.snake[0].x === this.food.x && this.snake[0].y === this.food.y) {
          if (this.snake[this.snake.length - 1].direction === 0) {
            this.snake.push({
              x: this.snake[this.snake.length - 1].x,
              y: this.snake[this.snake.length - 1].y + 1,
              color: this.defaultSelectColor,
              direction: this.snake[this.snake.length - 1].direction
            });
          } else if (this.snake[this.snake.length - 1].direction === 1) {
            this.snake.push({
              x: this.snake[this.snake.length - 1].x - 1,
              y: this.snake[this.snake.length - 1].y,
              color: this.defaultSelectColor,
              direction: this.snake[this.snake.length - 1].direction
            });
          } else if (this.snake[this.snake.length - 1].direction === 2) {
            this.snake.push({
              x: this.snake[this.snake.length - 1].x,
              y: this.snake[this.snake.length - 1].y - 1,
              color: this.defaultSelectColor,
              direction: this.snake[this.snake.length - 1].direction
            });
          } else if (this.snake[this.snake.length - 1].direction === 3) {
            this.snake.push({
              x: this.snake[this.snake.length - 1].x + 1,
              y: this.snake[this.snake.length - 1].y,
              color: this.defaultSelectColor,
              direction: this.snake[this.snake.length - 1].direction
            });
          }
          this.initSpeed();
          this.initFood();
        }
      },
      /**
       * 控制，通过wdsa进行控制
       * @param e
       */
      controlDirection(e) {
        if (e.key === 'w') {
          if (this.direction !== 2) {
            if (this.direction === 0) {
              this.nextSnake();
            } else {
              this.direction = 0;
            }
          }
        } else if (e.key === 'd') {
          if (this.direction !== 3) {
            if (this.direction === 1) {
              this.nextSnake();
            } else {
              this.direction = 1;
            }
          }
        } else if (e.key === 's') {
          if (this.direction !== 0) {
            if (this.direction === 2) {
              this.nextSnake();
            } else {
              this.direction = 2;
            }
          }
        } else if (e.key === 'a') {
          if (this.direction !== 1) {
            if (this.direction === 3) {
              this.nextSnake();
            } else {
              this.direction = 3;
            }
          }
        }
      },
      /**
       * 初始化时间间隔
       */
      initSpeed() {
        if (this.snake.length % 5 === 0) {
          this.intervalTime = this.intervalTime - (this.intervalTime / 3);
          clearInterval(this.interval);
          this.interval = setInterval(o => this.nextSnake(), this.intervalTime);
        } else if (this.snake.length === this.initLength) {
          clearInterval(this.interval);
          this.interval = setInterval(o => this.nextSnake(), this.intervalTime);
        }
      }
    },
    mounted() {
      // 初始化游戏
      this.initGame();
      // 时间间隔
      this.initSpeed();
    }
  });

  alert("wdsa分别控制上右下左");
</script>
</html>
